import os
import csv
import gdal
import json
from gdal import ogr
from tqdm import tqdm
import geojson
from sentinelsat import SentinelAPI, read_geojson, geojson_to_wkt
from datetime import date


class TL:

    def __init__(self):
        pass
    
    @staticmethod
    def ShapeFileToJsonList(shapefilepath, layername=None):
        """
        提取shp file中所有的feature 为json格式的列表
        :param shapefilepath:
        :param layername:
        :return:
        """
        datasource = ogr.Open(shapefilepath)
        if (layername is None) or layername == 0:
            layer = datasource.GetLayer(0)
        else:
            layer = datasource.GetLayerByName(layername)
        featurecount = layer.GetFeatureCount()
        featurejsonlist = []
        for featureindex in tqdm(range(featurecount)):
            feature = layer.GetFeature(featureindex)
            featurejson = feature.ExportToJson()
            featurejsonlist.append(featurejson)
        datasource.Destroy()
        return featurejsonlist

    @staticmethod
    def DataWriteGeoJsonFile(data, geojsonfilepath):
        with open(geojsonfilepath, 'w') as geojsonfile:
            geojson.dump(data, geojsonfile, indent=4)
        return

    @staticmethod
    def DataWriteJsonFile(data, jsonfilepath):
        with open(jsonfilepath, 'w+', encoding='utf-8') as jsonfile:
            json.dump(data, jsonfile, indent=4, ensure_ascii=False)
        return

    @staticmethod
    def JsonFileReadData(jsonfilepath):
        with open(jsonfilepath, 'r') as jsonfile:
            data = json.load(jsonfile)
        return data
    
    @staticmethod
    def JudgmentYear(year):
        """判断该年是否是瑞年"""
        if (year % 4) == 0:
            if (year % 100) == 0:
                if (year % 400) == 0:  # 整百年能被400整除的是闰年
                    yeardayc = 366
                else:  # 能被4整除的整百年且不能被400整除的是平年
                    yeardayc = 365
            else:  # 非整百年能被4整除的一定是闰年
                yeardayc = 366
        else:  # 不能被4整除的一定是平年
            yeardayc = 365
        return yeardayc

    @classmethod
    def YearMonthDayToNumber(cls, year, month, day):
        """计算某年某月某日是这一年的第几天"""
        monthday = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
        if cls.JudgmentYear(year) == 366:
            monthday[1] = 29
        daycount = sum(monthday[:month - 1]) + day
        return daycount

    @staticmethod
    def ShapeFileToGeojsonFile(shapefilepath, layername, geojsonfilepath):
        """
        把shape file矢量文件转为geojson格式矢量文件文件
        :param shapefilepath:
        :param layername:
        :param geojsonfilepath:
        :return:
        """
        datasource = ogr.Open(shapefilepath)
        if (layername is None) or layername == 0:
            layer = datasource.GetLayer(0)
        else:
            layer = datasource.GetLayerByName(layername)
        featurecount = layer.GetFeatureCount()
        for featureindex in range(featurecount):
            feature = layer.GetFeature(featureindex)
            # featurejson = feature.
        print(featurecount)
        return

    @staticmethod
    def WriteCSVFile(csvfilepath, header, infolist):
        """
        写入csv文件
        :param csvfilepath:
        :param header:
        :param infolist:
        :return:
        """
        file = open(csvfilepath, "w", encoding="gbk")
        csvwriter = csv.writer(file)
        csvwriter.writerow(header)
        for rowdata in infolist:
            csvwriter.writerow(rowdata)
        csvwriter = csv.writer(file)
        file.close()
        return

    @classmethod
    def GetGoalFile(cls, infolder, sign=None):
        """搜索获得目标文件路径集"""
        if sign is None:
            return cls.FindAllFile(infolder)
        elif sign[0] == r".":
            filepaths = cls.FindAllFile(infolder)
            rasfilepaths = [
                filepath
                for filepath in filepaths
                if os.path.splitext(os.path.split(filepath)[1])[1] == sign]
            return rasfilepaths
        else:
            filepaths = cls.FindAllFile(infolder)
            rasfilepaths = [
                filepath
                for filepath in filepaths
                if os.path.splitext(os.path.split(filepath)[1])[0] == sign]
            return rasfilepaths

    @classmethod
    def FindAllFile(cls, infolder):
        """寻找该目录下的所有文件"""
        names = os.listdir(infolder)
        filepaths = []
        for name in names:
            unkownfilefolder = os.path.join(infolder, name)
            if os.path.isfile(unkownfilefolder):
                filepaths.append(unkownfilefolder)
            elif os.path.isdir(unkownfilefolder):
                filepaths = filepaths + cls.FindAllFile(unkownfilefolder)
        return filepaths

    @classmethod
    def Getarea(cls, polygon):
        """
        给出任意一个多边形，其顶点坐标依次为（x0，y0），（x1，y1）
        ，（x2，y2），...，（xn，yn）（其中n=2，3，4，…），则其
        面积可表示为：
        """
        n = len(polygon)
        if n < 3:
            return 0
        area = 0
        for i in range(n - 2):
            # 以第一个坐标点为原点，将多边形分割为n-2个三角形，
            # 分别计算每个三角形面积后累加得多边形面积
            area += cls.CalculateTriangleArea(
                polygon[0], polygon[i + 1], polygon[i + 2])
        return abs(area)

    @staticmethod
    def CalculateTriangleArea(pointa, pointb, pointc):
        """向量叉乘法计算三角形面积"""
        trianglearea = 0.5 * (
                (pointb[0] - pointa[0]) * (pointc[1] - pointa[1]) -
                (pointb[1] - pointa[1]) * (pointc[0] - pointa[0]))
        return trianglearea

    @staticmethod
    def GetSubFile(pardir):
        """
        获取该文件夹下所有子文件路径
        """
        names = os.listdir(pardir)
        subfiles = []
        for name in names:
            unkownpath = os.path.join(pardir, name)
            if os.path.isfile(unkownpath):
                subfiles.append(unkownpath)
        return subfiles

    @staticmethod
    def GetSubDir(pardir):
        """获得所有子目录完整路径"""
        names = os.listdir(pardir)
        subdirs = []
        for name in names:
            unkownpath = os.path.join(pardir, name)
            if os.path.isdir(unkownpath):
                subdirs.append(unkownpath)
        return subdirs

    @staticmethod
    def HanziToPinyin(instr):
        """判断字符串中是否包含中文字符，若有，则用中文拼替换，没有，则返回原字符串"""
        outstrs = list(instr)
        strc = len(outstrs)
        for index in range(strc):
            if '\u4e00' <= outstrs[index] <= '\u9fff':
                hanzistr = outstrs[index]
                pinyinstrs = lazy_pinyin(hanzistr)  # 返回的是拼音列表
                pinyinstr = pinyinstrs[0]
                capitalpp = pinyinstr[0].upper() + pinyinstr[1:]
                outstrs[index] = capitalpp
        outstr = "".join(outstrs)
        return outstr

    @classmethod
    def GetEnglishNameFile(cls, inpath, outdir=None):
        """检查文件名中是否包含中文字符，如果包含，修改文件名并生成相应的文件"""
        basedir, filename = os.path.split(inpath)
        name, extend = os.path.splitext(filename)
        newname = cls.HanziToPinyin(name)
        if newname == name:
            print("%s文件名不包含中文字符！" % filename)
            return inpath
        if outdir is None:
            outpath = os.path.join(basedir, newname + extend)
        else:
            outpath = os.path.join(outdir, newname + extend)
        if os.path.exists(outpath):
            print("目标文件存在退出：\n%s" % outpath)
            return outpath
        shutil.copyfile(inpath, outpath)
        return outpath


class FileToolBox:
    
    username = "liangjiahao"
    password = "liangjiahao"
    sentineldownloadapiurl = "https://scihub.copernicus.eu/apihub/"
    sentineldownloaduiurl = "https://scihub.copernicus.eu/dhus"
    cloudcoverpercentageint = 30
    sentinel2processinglevel = 'Level-2A'
    
    def __init__(self, tl=TL):
        self.tl = tl
    
    @classmethod
    def Sentinel2Download(cls, countrygeojsonfilepath, starttime, endtime):
        # [startyear, startmonth, startday] = starttime
        # [endlayear, endmonth, endday] = endtime
        print(starttime)
        print(endtime)
        api = SentinelAPI(cls.username, cls.password, cls.sentineldownloaduiurl, show_progressbars=True, timeout=None)
        footprint = geojson_to_wkt(read_geojson(countrygeojsonfilepath))
        products = api.query(footprint,
                             date=(starttime, endtime), 
                             platformname="Sentinel-2",
                             producttype='S2MSI2A',
                             processinglevel=cls.sentinel2processinglevel,
                             cloudcoverpercentage=(0, cls.cloudcoverpercentageint))
        for product in products:
            product_info = api.get_product_odata(product)
            print(product_info['title'])
            api.download(product)
        return
    
    def DownloadSentinel2ByCountyNumber(self, countyjsonfilepath, geojsonfilepath, countyname, starttime, endtime):
        data = self.tl.JsonFileReadData(countyjsonfilepath)
        for item in data:
            fielddict = item["properties"]
            qhmcfield = fielddict["qhmc"]
            if qhmcfield == countyname:
                geodict = {"type": "FeatureCollection", "features": [{"type": "Feature", "properties": {}, "geometry": item["geometry"]}]}
                self.tl.DataWriteGeoJsonFile(geodict, geojsonfilepath)
                self.Sentinel2Download(geojsonfilepath, starttime, endtime)
                break
        return
    

FTB = FileToolBox
